#include "PeopleHistory.h"
#include "ServiceProvider.h"
#include "MatchData.h"
#include "ZStream.h"

// PeopleHistoryRecord

void PeopleHistoryRecord::Serialize(ZStream& o_stream) const
{
	o_stream.WriteOpenTag("PeopleHistoryRecord");
	o_stream.WriteAttribute("numSeason",	m_numSeason);
	o_stream.WriteAttribute("teamID",		m_teamID);
	o_stream.WriteAttribute("matchPlayed",	m_matchPlayed);
	o_stream.WriteAttribute("goalScored",	m_goalScored);
	o_stream.WriteAttribute("evaluations",	m_evaluations);
	o_stream.WriteAttribute("redCard",		m_redCard);
	o_stream.WriteAttribute("yellowCard",	m_yellowCard);
	o_stream.WriteAttribute("numOfInjury",	m_numOfInjury);
	o_stream.WriteAttribute("numOfInjuryDays",	m_numOfInjuryDays);
	o_stream.WriteAttribute("mom",	m_manOfTheMatch);
	o_stream.WriteCloseTag("PeopleHistoryRecord");
}

void PeopleHistoryRecord::Deserialize(ZStream& i_stream)
{
	i_stream.SkipLine();
	i_stream.ReadAttribute(m_numSeason);
	i_stream.ReadAttribute(m_teamID);
	i_stream.ReadAttribute(m_matchPlayed);
	i_stream.ReadAttribute(m_goalScored);
	i_stream.ReadAttribute(m_evaluations);
	i_stream.ReadAttribute(m_redCard);
	i_stream.ReadAttribute(m_yellowCard);
	i_stream.ReadAttribute(m_numOfInjury);
	i_stream.ReadAttribute(m_numOfInjuryDays);
	i_stream.ReadAttribute(m_manOfTheMatch);
	i_stream.SkipLine();
}

// PeopleHistory

int PeopleHistory::s_currentYear;

PeopleHistory::PeopleHistory()
{
	Clear();
}

void PeopleHistory::Clear()
{
	m_records.clear();

	m_status = StatusRetired;
	m_isBusy = false;
	m_birthYear = -1;
	m_startingYear = -1;
	m_playerRetirementYear = -1;
	m_trainerRetirementYear = -1;
}

ZStream& PeopleHistory::Serialize(ZStream& o_stream) const
{
	o_stream.WriteOpenTag("History");
	o_stream.WriteAttribute("HistoryNum",		m_records.size());

	for (PeopleHistoryRecordVecCit it = m_records.begin(); it != m_records.end(); ++it)
	{
		it->Serialize(o_stream);
	}

	o_stream.WriteAttribute("Status",		m_status);
	o_stream.WriteAttribute("IsBusy",		m_isBusy);
	o_stream.WriteAttribute("BirthYear",	m_birthYear);
	o_stream.WriteAttribute("StartingYear",	m_startingYear);
	o_stream.WriteAttribute("PlayerRetirementYear",	m_playerRetirementYear);
	o_stream.WriteAttribute("TrainerRetirementYear",	m_trainerRetirementYear);
	o_stream.WriteCloseTag("History");

	return o_stream;
}

ZStream& PeopleHistory::Deserialize(ZStream& i_stream)
{
	i_stream.SkipLine();

	size_t historyNum;

	i_stream.ReadAttribute(historyNum);

	m_records.clear();
	m_records.reserve(historyNum);

	for (size_t i = 0; i < historyNum; ++i)
	{
		PeopleHistoryRecord history;
		history.Deserialize(i_stream);
		m_records.push_back(history);
	}

	i_stream.ReadAttribute(m_status);
	i_stream.ReadAttribute(m_isBusy);
	i_stream.ReadAttribute(m_birthYear);
	i_stream.ReadAttribute(m_startingYear);
	i_stream.ReadAttribute(m_playerRetirementYear);
	i_stream.ReadAttribute(m_trainerRetirementYear);
	i_stream.SkipLine();

	return i_stream;
}

const STD::pair<size_t,size_t> PeopleHistory::GetIndexYearRange(const size_t i_first, const size_t i_last) const
{
	size_t first_index = 0;
	size_t num_index = 0;

	size_t index = 0;

	while(index < m_records.size() && m_records[index].m_numSeason < i_first)
	{
		first_index = index;
		num_index++;

		while(m_records[index].m_numSeason <= i_last)
		{
			num_index++;
			index++;
		}
	}

	return STD::pair<size_t, size_t>(first_index, first_index + num_index);
}

const int PeopleHistory::GetNumOfInjury() const 
{
	//TODO: bug: what if more than 1 record of current season?
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().m_numOfInjury : 0;
}

const int PeopleHistory::GetNumOfInjuryDays() const 
{
	//TODO: bug: what if more than 1 record of current season?
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().m_numOfInjuryDays : 0;
}

const size_t PeopleHistory::GetMatch() const
{
	//TODO: bug: what if more than 1 record of current season?
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().m_matchPlayed : 0;
}

const size_t PeopleHistory::GetScoredGoal() const
{
	//TODO: bug: what if more than 1 record of current season?
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().m_goalScored : 0;
}

const int PeopleHistory::GetRedCard() const
{
	//TODO: bug: what if more than 1 record of current season?
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().m_redCard : 0;
}

const int PeopleHistory::GetYellowCard() const
{
	//TODO: bug: what if more than 1 record of current season?
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().m_yellowCard : 0;
}

const float PeopleHistory::GetScoredGoalRatio() const
{
	//TODO: bug: what if more than 1 record of current season?
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().GetRatio() : -1.0f;
}

const size_t PeopleHistory::GetEval() const
{
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().GetEval() : 0;
}

const STL::string PeopleHistory::GetEvalStr() const
{
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().GetEvalStr() : "----";
}

const int PeopleHistory::GetMoM() const
{
	return (!m_records.empty() && IsBusy(StatusPlayer)) ? m_records.back().m_manOfTheMatch : 0;
}

const int PeopleHistory::GetTotalMoM() const
{
	int total = 0;
	for(size_t i = 0; i < m_records.size(); i++)
		total += m_records[i].m_manOfTheMatch;
	
	return total;
}

const size_t PeopleHistory::GetTotalScoredGoal() const
{
	size_t totalScoredGoal = 0;
	for(size_t i = 0; i < m_records.size(); i++)
		totalScoredGoal += m_records[i].m_goalScored;
	
	return totalScoredGoal;
}

const int PeopleHistory::GetTotalRedCard() const
{
	size_t totalRedCard = 0;
	for(size_t i = 0; i < m_records.size(); i++)
		totalRedCard += m_records[i].m_redCard;
	
	return totalRedCard;
}

const int PeopleHistory::GetTotalYellowCard() const
{
	size_t totalYellowCard = 0;
	for(size_t i = 0; i < m_records.size(); i++)
		totalYellowCard += m_records[i].m_yellowCard;
	
	return totalYellowCard;
}

const int PeopleHistory::GetTotalDisciplinePoints() const
{
	int retVal = 0;
	for(size_t i = 0; i < m_records.size(); i++)
		retVal += m_records[i].m_yellowCard + m_records[i].m_redCard * 3;
	
	return retVal;
}

const int PeopleHistory::GetTotalNumOfInjury() const
{
	size_t totalNumOfInjuries = 0;
	for(size_t i = 0; i < m_records.size(); i++)
		totalNumOfInjuries += m_records[i].m_numOfInjury;
	
	return totalNumOfInjuries;
}

const int PeopleHistory::GetTotalNumOfInjuryDays() const
{
	size_t totalNumOfInjuriesDays = 0;
	for(size_t i = 0; i < m_records.size(); i++)
		totalNumOfInjuriesDays += m_records[i].m_numOfInjuryDays;
	
	return totalNumOfInjuriesDays;
}

const size_t PeopleHistory::GetTotalMatch(const int i_status) const
{
	size_t totalMatch = 0;
	for(size_t i = 0; i < m_records.size(); i++)
		if(WasStatus(m_records[i].m_numSeason, i_status))
			totalMatch += m_records[i].m_matchPlayed;

	return totalMatch;
}

const size_t PeopleHistory::GetTotalEval() const
{
	const size_t totalMatch = GetTotalMatch(StatusPlayer);
	if(totalMatch == 0)
		return 0;

	size_t totalEval = 0;
	for(size_t i = 0; i < m_records.size(); i++)
		if(WasStatus(m_records[i].m_numSeason, StatusPlayer))
			totalEval += m_records[i].m_evaluations;

	return totalEval/totalMatch;
}

const STL::string PeopleHistory::GetTotalEvalStr() const
{
	const size_t eval = GetTotalEval();
	return EvalToStr(eval);
}

const STL::string EvalToStr(const size_t i_eval)
{
	if(i_eval == 0)
		return "----";
	char temp[10];
	if(i_eval!=1000)
		sprintf_s(temp, 10, "%d.%d%d", i_eval/100, (i_eval/10)%10, i_eval%10);
	else
		return "10.0";
	return temp;
}

void PeopleHistory::AddMatch(const int i_scoredGoals, const int i_evaluation, const bool i_isMoM, const int i_card, const int i_dayInjury)
{
	PeopleHistoryRecord& rec = m_records.back();

	++rec.m_matchPlayed;
	rec.m_evaluations += i_evaluation;
	rec.m_goalScored += i_scoredGoals;
	if(i_isMoM) 
		++rec.m_manOfTheMatch;
	if(i_dayInjury) 
	{
		++rec.m_numOfInjury;
		rec.m_numOfInjuryDays += i_dayInjury;
	}
	if(IsYellowCard(i_card))
		++rec.m_yellowCard;
	if(IsRedCard(i_card))
		++rec.m_redCard;
}

